from django.contrib.auth import login, logout
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
from django.http import HttpResponseForbidden, JsonResponse, HttpResponse
import re
from django_redis import get_redis_connection
from .models import User, Area, Address
from random import randint
from . import constants
from celery_tasks.sms.tasks import CSSC
from celery_tasks.emile.tasks import take_email
from django.contrib.auth import authenticate
from django.contrib.auth.mixins import LoginRequiredMixin
import json
from django.core import signing
from django.core.cache import cache


class RegisterView(View):
    # 注册
    def get(self, request):
        return render(request, 'register.html')

    def post(self, request):
        username = request.POST.get('user_name')
        password = request.POST.get('pwd')
        password2 = request.POST.get('cpwd')
        mobile = request.POST.get('phone')
        sms_code = request.POST.get('msg_code')
        allow = request.POST.get('allow')

        if not all([username, password, mobile, sms_code, allow]):
            return HttpResponseForbidden('信息填写不完全')
        if allow != 'on':
            return HttpResponseForbidden('请阅读并同意用户协议')
        # 验证用户名格式
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return HttpResponseForbidden('用户名格式错误')
        if User.objects.filter(username=username).count() > 0:
            return HttpResponseForbidden('已注册的用户名')
        # 验证密码格式
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return HttpResponseForbidden('密码格式错误')
        if password != password2:
            return HttpResponseForbidden('两次密码输入不一致')
        # 验证手机号格式
        if not re.match(r'^1[345789]\d{9}$', mobile):
            return HttpResponseForbidden('手机号格式错误')
        if User.objects.filter(mobile=mobile).count() > 0:
            return HttpResponseForbidden('已注册的手机号')
        redis_conn = get_redis_connection('verify_code')
        sms_code_server = redis_conn.get('sms_%s' % mobile)
        if not sms_code_server:
            return HttpResponseForbidden('验证码已失效')
        if sms_code_server.decode() != sms_code:
            return HttpResponseForbidden('验证码输入错误')

        # 存入数据库
        try:
            user = User.objects.create_user(username=username, password=password, mobile=mobile)
        except:
            return render(request, 'register.html', {'register_errmsg': '注册失败!!!!'})

        login(request, user)

        return redirect(reverse('contents:index'))


class UsernameCountView(View):
    def get(self, request, username):
        count = User.objects.filter(username=username).count()
        return JsonResponse({'code': 'ok', 'errmsg': 'OK', 'count': count})


class MobileCountView(View):
    def get(self, request, mobile):
        count = User.objects.filter(mobile=mobile).count()
        return JsonResponse({'code': 'ok', 'errmsg': 'OK', 'count': count})


class SmsCodeView(View):
    def get(self, request, mobile):
        text = request.GET.get('image_code')
        uuid = request.GET.get('image_code_id')
        if not all([mobile, text, uuid]):
            return JsonResponse({'code': 1, 'errmsg': '缺少必要的参数'})
        redis_conn = get_redis_connection('verify_code')
        image_server = redis_conn.get('img_%s' % uuid)
        if not image_server:
            return JsonResponse({'code': 1, 'errmsg': '验证码已过期'})
        # if User.objects.filter(mobile=mobile).count() > 0:
        #     return JsonResponse({'code': 1, 'errmsg': '手机号已注册'})
        if not image_server:
            return JsonResponse({'code': 1, 'errmsg': '验证码已过期'})
        if image_server.decode().lower() != text.lower():
            return JsonResponse({'code': 1, 'errmsg': '验证码输入错误'})
        if redis_conn.get('sms_%s' % mobile):
            return JsonResponse({'code': 1, 'errmsg': '请求的太频繁'})
        sms_code = '%6d' % randint(0, 999999)
        redis_conn.setex('sms_%s' % mobile, constants.SCRE, sms_code)
        CSSC(sms_code)
        return JsonResponse({'code': 1, 'errmsg': '发送成功'})


class LoginView(View):
    def get(self, request):
        return render(request, 'login.html')

    def post(self, request):
        username = request.POST.get('username')
        password = request.POST.get('pwd')
        remembered = request.POST.get('remembered')
        next = request.GET.get('next')
        if not all([username, password]):
            return HttpResponseForbidden('不完整的信息')
        user = authenticate(username=username, password=password)
        if not user:
            return render(request, 'login.html', {'loginerror': '用户名或密码错误'})
        login(request, user)
        if remembered != 'on':
            request.session.set_expiry(0)
        else:
            request.session.set_expiry(None)
        if next:
            respones = redirect(next)
        else:
            respones = redirect(reverse('contents:index'))
        respones.set_cookie('username', user.username, max_age=60 * 60 * 24 * 15)
        return respones


class LogoutView(View):
    def get(self, request):
        logout(request)
        respones = redirect(reverse('contents:index'))
        respones.delete_cookie('username')
        return respones


class InfoView(LoginRequiredMixin, View):
    def get(self, request):
        context = {
            'username': request.user.username,
            'mobile': request.user.mobile,
            'email': request.user.email,
            'email_active': request.user.email_active
        }
        return render(request, 'user_center_info.html', context)


class EmailsView(LoginRequiredMixin, View):
    def put(self, request):
        json_dict = json.loads(request.body.decode())
        email = json_dict.get('email')
        if not email:
            return HttpResponseForbidden('缺少参数')
        if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
            return HttpResponseForbidden('邮箱格式错误')
        try:
            request.user.email = email
            request.user.save()
        except:
            return HttpResponseForbidden('邮箱添加失败')
        user = request.user
        take_email(user_id=user.id, user_email=user.email)
        return JsonResponse({'code': 0, 'errmsg': '添加成功,发送验证邮件'})


class EmailVerification(View):
    def get(self, request):
        value = request.GET.get('value')
        if not value:
            return HttpResponseForbidden('缺少值')
        try:
            data = signing.loads(value)
            user_id = data.get('user_id')
            email = data.get('email')
        except:
            return HttpResponseForbidden('错误的值')
        try:
            user = User.objects.get(id=user_id, email=email)
        except:
            return HttpResponseForbidden('错误的用户')
        try:
            user.email_active = True
            user.save()
        except:
            return HttpResponseForbidden('激活失败')
        return redirect(reverse('users:info'))


class AddressView(LoginRequiredMixin, View):
    def get(self, request):
        user = request.user
        addresses = Address.objects.filter(user=user, is_deleted=0)
        data = [{'title': i.title,
                 'receiver': i.receiver,
                 'place': i.place,
                 'mobile': i.mobile,
                 'tel': i.tel,
                 'email': i.email,
                 'city': i.city.name,
                 'district': i.district.name,
                 'province': i.province.name,
                 'province_id': i.province_id,
                 'city_id': i.city_id,
                 'district_id': i.district_id,
                 'id': i.id
                 } for i in addresses]
        context = {
            'addresses': data,
            'default_address_id': user.default_address_id
        }
        return render(request, 'user_center_site.html', context)


class AddressAddView(LoginRequiredMixin, View):
    def post(self, request):
        data = json.loads(request.body.decode())
        title = data['title']
        receiver = data["receiver"]
        province_id = data["province_id"]
        city_id = data["city_id"]
        district_id = data["district_id"]
        place = data["place"]
        mobile = data["mobile"]
        tel = data["tel"]
        email = data["email"]
        if Address.objects.filter(user=request.user).count() >= 20:
            return JsonResponse({'code': 1, 'errmsg': '完成码'})
        if not all([title, receiver, province_id, city_id, district_id, place, mobile]):
            return JsonResponse({'code': 1, 'errmsg': '数据不完整'})
        if not re.match(r'^1[345789]\d{9}$', mobile):
            return JsonResponse({'code': 4007, 'errmsg': '手机号格式错误'})
        try:
            address = Address.objects.create(title=title, receiver=receiver, province_id=province_id,
                                             city_id=city_id,
                                             district_id=district_id,
                                             place=place,
                                             mobile=mobile, tel=tel, email=email, user=request.user)
            request.user.default_address_id = address
            request.user.save()
        except:
            return JsonResponse({'code': 1, 'errmsg': '添加失败'})
        return JsonResponse({'code': 0,
                             'errmsg': 'OK',
                             'address': {
                                 'title' : address.title,
                                 'id': address.id,
                                 'receiver': address.receiver,
                                 'province': address.province.name,
                                 'province_id': address.province_id,
                                 'city': address.city.name,
                                 'city_id': address.city_id,
                                 'district': address.district.name,
                                 'district_id': address.district_id,
                                 'place': address.place,
                                 'mobile': address.mobile,
                                 'tel': address.tel,
                                 'email': address.email
                             }
                             }
                            )


class AddressReturnView(LoginRequiredMixin, View):
    def get(self, request):
        # 省市区三级联动
        area_id = request.GET.get('area_id')
        area = cache.get('area_%s' % area_id)
        if not area:
            if not area_id:
                area = Area.objects.filter(parent=None)
                try:
                    a = [{'name': i.name, 'id': i.id} for i in area]
                    cache.set('area_%s' % area_id, a, 60 * 60)
                except:
                    return JsonResponse({'code': 1, 'errmsg': '省份数据错误'})
            else:
                area = Area.objects.filter(parent_id=area_id)
                try:
                    a = [{'name': i.name, 'id': i.id} for i in area]
                    cache.set('area_%s' % area_id, a, 60 * 60)
                except:
                    return JsonResponse({'code': 1, 'errmsg': '城市或区数据错误'})
        else:
            a = area
        return JsonResponse({'code': 0, 'sub_data': a})


class AddressDefaultView(LoginRequiredMixin, View):
    # 设置默认地址
    def put(self, request, address_id):
        request.user.default_address_id = address_id
        try:
            request.user.save()
        except:
            return JsonResponse({'code': 1, 'errmsg': '设置失败'})
        return JsonResponse({'code': 0})


class AddressReView(LoginRequiredMixin, View):
    def put(self, request, address_id):
        # 修改地址
        address = json.loads(request.body.decode())
        city = address['city']
        city_id = address['city_id']
        district = address['district']
        district_id = address['district_id']
        email = address['email']
        id = address['id']
        mobile = address['mobile']
        place = address['place']
        province = address['province']
        province_id = address['province_id']
        receiver = address['receiver']
        tel = address['tel']
        title = address['title']
        if not all([city, city_id, district_id, district, id, mobile, place, province, province_id, receiver, title]):
            return JsonResponse({'code': 1, 'errmsg': '数据不全'})
        if not re.match(r'1[345789]\d{9}', mobile):
            return JsonResponse({'code': 4007, 'errmsg': '手机号格式错误'})
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return JsonResponse({'code': 5001, 'errmsg': 'email格式错误'})
        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return JsonResponse({'code': 5002, 'errmsg': '电话号码格式错误'})
        try:
            # Address.objects.get(id=id).delete()
            address = Address.objects.get(id=id, is_deleted=0)
            address.receiver = receiver
            address.city_id = city_id
            address.district_id = district_id
            address.province_id = province_id
            address.place = place
            address.mobile = mobile
            address.tel = tel
            address.email = email
            address.save()
        except:
            return JsonResponse({'code': 1, 'errmsg': '找不到收获地址id'})
        # Address.objects.create(city_object has no attributeid=city_id, district_id=district_id, email=email, id=id, mobile=mobile, place=place,
        #                        province_id=province_id, receiver=receiver, title=title, user=request.user)
        return JsonResponse({'code': 0,
                             'address': {"id": address_id, "title": address.title, "receiver": address.receiver,
                                         "province": address.province.name, "province_id": address.province_id,
                                         "city": address.city.name, "city_id": address.city_id,
                                         "district": address.district.name, "district_id": address.district_id,
                                         "place": address.place, "mobile": address.mobile, "tel": address.tel,
                                         "email": address.email}})

    def delete(self, request, address_id):
        # 删除地址
        try:
            address = Address.objects.get(id=address_id)
            address.is_deleted = 1
            address.save()
        except:
            return JsonResponse({'code': 0, 'errmsh': '删除失败'})
        return JsonResponse({'code': 0, 'errmsg': '成功'})


class AddressTitleView(LoginRequiredMixin, View):
    def put(self, request, address_id):
        data = json.loads(request.body.decode())
        title = data['title']
        try:
            Address.objects.filter(id=address_id).update(title=title)
            return JsonResponse({'code': 0, 'errmsg': '成功'})
        except:
            return JsonResponse({'code': 1, 'errmsg': '修改失败'})


class PasswordView(LoginRequiredMixin, View):
    def get(self, request):
        return render(request, 'user_center_pass.html')

    def post(self, request):
        old_pwd = request.POST.get('old_pwd')
        new_pwd = request.POST.get('new_pwd')
        new_cpwd = request.POST.get('new_cpwd')
        if not all([old_pwd, new_pwd, new_cpwd]):
            return HttpResponseForbidden('信息不完整')
        if not request.user.check_password(old_pwd):
            return HttpResponseForbidden('无效的密码')
        if not re.match(r'[0-9A-Za-z]{8,20}', old_pwd) and re.match(r'[0-9A-Za-z]{8,20}', new_cpwd):
            return HttpResponseForbidden('密码格式错误')
        if new_pwd != new_cpwd:
            return HttpResponseForbidden('两次密码不一致')
        try:
            request.user.set_password(new_pwd)
            request.user.save()
        except:
            return HttpResponseForbidden('修改失败')
        logout(request)
        return redirect(reverse('users:login'))


class NewView(View):
    def get(self, request):
        return render(request, 'new.html')
